﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Collections;


namespace AlgoLogicServer
{
    class Server
    {
        public static List<User> clientsList = new List<User>();

        static void Main(string[] args)
        {
            TcpListener serverSocket = new TcpListener(8888);
            TcpClient clientSocket = default(TcpClient);
            int counter = 0;

            serverSocket.Start();
            Console.WriteLine("Chat Server Started ....");
            while ((true))
            {
                counter += 1;
                clientSocket = serverSocket.AcceptTcpClient();
                int bufferSize = clientSocket.ReceiveBufferSize;
               // byte[] bytesFrom = new byte[bufferSize];
                byte[] bytesFrom = new byte[bufferSize];
                string dataFromClient = null;

                NetworkStream networkStream = clientSocket.GetStream();
                //networkStream.Read(bytesFrom, 0, bufferSize);
                networkStream.Read(bytesFrom, 0, bufferSize);
                dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("#"));

                User tempUser = new User(counter, dataFromClient, clientSocket);

                clientsList.Add(tempUser);
                handleClinet client = new handleClinet();
                client.startClient(clientSocket, tempUser, clientsList, counter);
            }

            clientSocket.Close();
            serverSocket.Stop();
            Console.WriteLine("exit");
            Console.ReadLine();
        }

        public static void broadcast(string msg, User userObject, bool flag, int index)
        {
            string[] filterMsg = msg.Split('|');

            if (filterMsg[0].ToString() == "@command")
            {
                if (filterMsg[1].ToString() == "changeUName")
                {
                    for (int i = 0; i < clientsList.Count; i++)
                    {
                        if (clientsList[i].Index == index)
                        {
                            //Check against the database
                            DBManager CheckTeamName = new DBManager();
                            CheckTeamName.TeamName = filterMsg[2].ToString();

                            if (CheckTeamName.RetreiveTeamName() == false)
                            {
                                clientsList[i].UniqueName = filterMsg[2].ToString();
                                //Add team name into database
                                DBManager AddTeamName = new DBManager();
                                AddTeamName.TeamName = clientsList[i].UniqueName;
                                AddTeamName.Date = DateTime.Today;
                                AddTeamName.InsertTeamName();

                                foreach (User item in clientsList)
                                {
                                    TcpClient broadcastSocket;
                                    broadcastSocket = (TcpClient)item.ClientSocket;
                                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                                    Byte[] broadcastBytes = null;

                                    if (broadcastStream.CanWrite)
                                    {
                                        broadcastBytes = Encoding.ASCII.GetBytes(filterMsg[2].ToString() + "|TeamCreated!|");
                                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                                        broadcastStream.Flush();
                                    }
                                    else
                                    {
                                        Console.WriteLine("Sorry. You cannot write to this NetworkStream.");
                                    }
                                }
                            }
                            else
                            {
                                foreach (User item in clientsList)
                                {
                                    TcpClient broadcastSocket;
                                    broadcastSocket = (TcpClient)item.ClientSocket;
                                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                                    Byte[] broadcastBytes = null;

                                    if (broadcastStream.CanWrite)
                                    {
                                        broadcastBytes = Encoding.ASCII.GetBytes(filterMsg[2].ToString() + "|NameUsed!|");
                                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                                        broadcastStream.Flush();
                                    }
                                    else
                                    {
                                        Console.WriteLine("Sorry. You cannot write to this NetworkStream.");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@logout")
            {
                foreach (User item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@image")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@massConvo")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@SendToComp")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }

            else if (filterMsg[0].ToString() == "@UpdateComp")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }

            else if (filterMsg[0].ToString() == "@comConv")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@EndComConv")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@faster")
            {
                foreach (User Item in clientsList)
                {
                    Thread.Sleep(100);
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@comAnsConv")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@displayTime")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@time")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@stop")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@pause")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@resumePause")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@quizStart")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@videoStart")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@back")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@videoPlay")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }

            else if (filterMsg[0].ToString() == "@videoName")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@Score")
            {
                foreach (User Item in clientsList)
                {
                    Thread.Sleep(100);
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@AllowNavigation")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@DisallowNavigation")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@ForceAllLogOut")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@Msg")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@Talk")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
            else if (filterMsg[0].ToString() == "@talkConvo")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }

            else if (filterMsg[0].ToString() == "@displayMsgBox")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }

            else if (filterMsg[0].ToString() == "@checkVulgar")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }

            else if (filterMsg[0].ToString() == "@startFacilTimer")
            {
                foreach (User Item in clientsList)
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.ClientSocket;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (broadcastStream.CanWrite)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                        broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                        broadcastStream.Flush();
                    }
                }
            }
        }  //end broadcast function

        public class handleClinet
        {
            TcpClient clientSocket;
            User client;
            List<User> clientsList;
            int counter;

            public void startClient(TcpClient inClientSocket, User client, List<User> cList, int counter)
            {
                this.clientSocket = inClientSocket;
                this.client = client;
                this.clientsList = cList;
                this.counter = counter;
                Thread ctThread = new Thread(doChat);
                ctThread.Start();
            }

            private void doChat()
            {
                int bufferSize = clientSocket.ReceiveBufferSize;

                int requestCount = 0;
                //byte[] inStream = new byte[65536];
                byte[] bytesFrom = new byte[bufferSize];
                string dataFromClient = null;
                Byte[] sendBytes = null;
                string serverResponse = null;
                string rCount = null;
                requestCount = 0;

                while ((true))
                {
                    try
                    {
                        requestCount = requestCount + 1;
                        NetworkStream networkStream = clientSocket.GetStream();
                        networkStream.Read(bytesFrom, 0, bufferSize);
                        dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                        if (!dataFromClient.StartsWith("\0"))
                        {
                            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("#"));
                            Console.WriteLine(client.UniqueName + ": " + dataFromClient);
                            rCount = Convert.ToString(requestCount);

                            Server.broadcast(dataFromClient, client, true, counter);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                    if (clientSocket.Connected != true)
                    {
                        clientsList.Clear();
                        Environment.Exit(1);
                    }
                }//end while                
            }//end doChat
        } //end class handleClinet
    }
}